home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / sh.glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-21  |  19.5 KB  |  927 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.glob.c,v 3.9 1991/08/06 01:00:15 christos Exp $ */
  2. /*
  3.  * sh.glob.c: Regular expression expansion
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "config.h"
  38. RCSID("$Id: sh.glob.c,v 3.9 1991/08/06 01:00:15 christos Exp $")
  39.  
  40. #include "sh.h"
  41. #include "tc.h"
  42.  
  43. #include <glob.h>
  44.  
  45. static int noglob;
  46. static int pargsiz, gargsiz;
  47.  
  48. /*
  49.  * Values for gflag
  50.  */
  51. #define    G_NONE    0        /* No globbing needed            */
  52. #define    G_GLOB    1        /* string contains *?[] characters    */
  53. #define    G_CSH    2        /* string contains ~`{ characters    */
  54.  
  55. #define    GLOBSPACE    100    /* Alloc increment            */
  56.  
  57. #define LBRC '{'
  58. #define RBRC '}'
  59. #define LBRK '['
  60. #define RBRK ']'
  61. #define EOS '\0'
  62.  
  63. Char  **gargv = NULL;
  64. long    gargc = 0;
  65. Char  **pargv = NULL;
  66. long    pargc = 0;
  67.  
  68. /*
  69.  * globbing is now done in two stages. In the first pass we expand
  70.  * csh globbing idioms ~`{ and then we proceed doing the normal
  71.  * globbing if needed ?*[
  72.  *
  73.  * Csh type globbing is handled in globexpand() and the rest is
  74.  * handled in glob() which is part of the 4.4BSD libc.
  75.  *
  76.  */
  77. static    Char     *globtilde    __P((Char **, Char *));
  78. static    Char     *globequal    __P((Char **, Char *));
  79. static    Char    **libglob    __P((Char **));
  80. static    Char    **globexpand    __P((Char **));
  81. static    int      globbrace    __P((Char *, Char *, Char ***));
  82. static    void      pword        __P((void));
  83. static    void      psave        __P((int));
  84. static    void      backeval    __P((Char *, bool));
  85.  
  86. static Char *
  87. globtilde(nv, s)
  88.     Char  **nv, *s;
  89. {
  90.     Char    gbuf[MAXPATHLEN], *gstart, *b, *u, *e;
  91. #ifdef apollo
  92.     int slash;
  93. #endif
  94.  
  95.     gstart = gbuf;
  96.     *gstart++ = *s++;
  97.     u = s;
  98. #ifdef __MINT__
  99.     for (b = gstart, e = &gbuf[MAXPATHLEN-1]; *s && *s != '/' && *s != '\\' &&
  100.         b < e;
  101. #else
  102.     for (b = gstart, e = &gbuf[MAXPATHLEN - 1]; *s && *s != '/' && b < e;
  103. #endif
  104.      *b++ = *s++);
  105.     *b = EOS;
  106.     if (gethdir(gstart)) {
  107.     blkfree(nv);
  108.     if (*gstart)
  109.         stderror(ERR_UNKUSER, short2str(gstart));
  110.     else
  111.         stderror(ERR_NOHOME);
  112.     }
  113.     b = &gstart[Strlen(gstart)];
  114. #ifdef apollo
  115.     slash = gstart[0] == '/' && gstart[1] == '\0';
  116. #endif
  117.     while (*s)
  118.     *b++ = *s++;
  119.     *b = EOS;
  120.     --u;
  121.     xfree((ptr_t) u);
  122. #ifdef apollo
  123.     if (slash && gstart[1] == '/')
  124.     gstart++;
  125. #endif
  126.     return (Strsave(gstart));
  127. }
  128.  
  129. static Char *
  130. globequal(nv, s)
  131.     Char  **nv, *s;
  132. {
  133.     int     dig;
  134.     Char    gp[MAXPATHLEN], *b, *d;
  135.  
  136.     /*
  137.      * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
  138.      * in stack. PWP: let =foobar pass through (for X windows)
  139.      */
  140. #ifdef __MINT__
  141.     if ((Isdigit(s[1]) || s[1] == '-') && (s[2] == '\0' || s[2] == '/' ||
  142.                          s[2] == '\\')) {
  143. #else
  144.     if ((Isdigit(s[1]) || s[1] == '-') && (s[2] == '\0' || s[2] == '/')) {
  145. #endif
  146.     dig = (s[1] == '-') ? -1 : s[1] - '0';
  147.     if (!getstakd(gp, dig)) {
  148.         blkfree(nv);
  149.         stderror(ERR_DEEP);
  150.     }
  151.     for (b = &s[2], d = &gp[Strlen(gp)]; *d++ = *b++;);
  152.     xfree((ptr_t) s);
  153.     return (Strsave(gp));
  154.     }
  155.     else
  156.     return (s);
  157. }
  158.  
  159. static int
  160. globbrace(s, p, bl)
  161.     Char   *s, *p, ***bl;
  162. {
  163.     int     i, len;
  164.     Char   *pm, *pe, *lm, *pl;
  165.     Char  **nv, **vl;
  166.     Char    gbuf[MAXPATHLEN];
  167.     int     size = GLOBSPACE;
  168.  
  169.     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
  170.     *vl = NULL;
  171.  
  172.     len = 0;
  173.     /* copy part up to the brace */
  174.     for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
  175.     continue;
  176.  
  177.     /* check for balanced braces */
  178.     for (i = 0, pe = ++p; *pe; pe++)
  179.     if (*pe == LBRK) {
  180.         /* Ignore everything between [] */
  181.         for (++pe; *pe != RBRK && *pe != EOS; pe++)
  182.         continue;
  183.         if (*pe == EOS) {
  184.         blkfree(nv);
  185.         return (-RBRK);
  186.         }
  187.     }
  188.     else if (*pe == LBRC)
  189.         i++;
  190.     else if (*pe == RBRC) {
  191.         if (i == 0)
  192.         break;
  193.         i--;
  194.     }
  195.  
  196.     if (i != 0 || *pe == '\0') {
  197.     blkfree(nv);
  198.     return (-RBRC);
  199.     }
  200.  
  201.     for (i = 0, pl = pm = p; pm <= pe; pm++)
  202.     switch (*pm) {
  203.     case LBRK:
  204.         for (++pm; *pm != RBRK && *pm != EOS; pm++)
  205.         continue;
  206.         if (*pm == EOS) {
  207.         *vl = NULL;
  208.         blkfree(nv);
  209.         return (-RBRK);
  210.         }
  211.         break;
  212.     case LBRC:
  213.         i++;
  214.         break;
  215.     case RBRC:
  216.         if (i) {
  217.         i--;
  218.         break;
  219.         }
  220.         /* FALLTHROUGH */
  221.     case ',':
  222.         if (i && *pm == ',')
  223.         break;
  224.         else {
  225.         Char    savec = *pm;
  226.  
  227.         *pm = EOS;
  228.         (void) Strcpy(lm, pl);
  229.         (void) Strcat(gbuf, pe + 1);
  230.         *pm = savec;
  231.         *vl++ = Strsave(gbuf);
  232.         len++;
  233.         pl = pm + 1;
  234.         if (vl == &nv[size]) {
  235.             size += GLOBSPACE;
  236.             nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  237.                         size * sizeof(Char *));
  238.             vl = &nv[size - GLOBSPACE];
  239.         }
  240.         }
  241.         break;
  242.     }
  243.     *vl = NULL;
  244.     *bl = nv;
  245.     return (len);
  246. }
  247.  
  248. static Char **
  249. globexpand(v)
  250.     Char  **v;
  251. {
  252.     Char   *s;
  253.     Char  **nv, **vl, **el;
  254.     int     size = GLOBSPACE;
  255.  
  256.  
  257.     nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
  258.     *vl = NULL;
  259.  
  260.     /*
  261.      * Step 1: expand backquotes.
  262.      */
  263.     while (s = *v++) {
  264.     if (Strchr(s, '`')) {
  265.         int     i;
  266.  
  267.         (void) dobackp(s, 0);
  268.         for (i = 0; i < pargc; i++) {
  269.         *vl++ = pargv[i];
  270.         if (vl == &nv[size]) {
  271.             size += GLOBSPACE;
  272.             nv = (Char **) xrealloc((ptr_t) nv,
  273.                         (size_t) size * sizeof(Char *));
  274.             vl = &nv[size - GLOBSPACE];
  275.         }
  276.         }
  277.         xfree((ptr_t) pargv);
  278.         pargv = NULL;
  279.     }
  280.     else {
  281.         *vl++ = Strsave(s);
  282.         if (vl == &nv[size]) {
  283.         size += GLOBSPACE;
  284.         nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  285.                     size * sizeof(Char *));
  286.         vl = &nv[size - GLOBSPACE];
  287.         }
  288.     }
  289.     }
  290.     *vl = NULL;
  291.  
  292.     if (noglob)
  293.     return (nv);
  294.  
  295.     /*
  296.      * Step 2: expand braces
  297.      */
  298.     el = vl;
  299.     vl = nv;
  300.     for (s = *vl; s; s = *++vl) {
  301.     Char   *b;
  302.     Char  **vp, **bp;
  303.  
  304.     if ((b = Strchr(s, LBRC)) && b[1] != '\0' && b[1] != RBRC) {
  305.         Char  **bl;
  306.         int     len;
  307.  
  308.         if ((len = globbrace(s, b, &bl)) < 0) {
  309.         blkfree(nv);
  310.         stderror(ERR_MISSING, -len);
  311.         }
  312.         xfree((ptr_t) s);
  313.         if (len == 1) {
  314.         *vl-- = *bl;
  315.         xfree((ptr_t) bl);
  316.         continue;
  317.         }
  318.         len = blklen(bl);
  319.         if (&el[len] >= &nv[size]) {
  320.         int     l, e;
  321.  
  322.         l = &el[len] - &nv[size];
  323.         size += GLOBSPACE > l ? GLOBSPACE : l;
  324.         l = vl - nv;
  325.         e = el - nv;
  326.         nv = (Char **) xrealloc((ptr_t) nv, (size_t)
  327.                     size * sizeof(Char *));
  328.         vl = nv + l;
  329.         el = nv + e;
  330.         }
  331.         vp = vl--;
  332.         *vp = *bl;
  333.         len--;
  334.         for (bp = el; bp != vp; bp--)
  335.         bp[len] = *bp;
  336.         el += len;
  337.         vp++;
  338.         for (bp = bl + 1; *bp; *vp++ = *bp++)
  339.         continue;
  340.         xfree((ptr_t) bl);
  341.     }
  342.  
  343.     }
  344.  
  345.     /*
  346.      * Step 3: expand ~ =
  347.      */
  348.     vl = nv;
  349.     for (s = *vl; s; s = *++vl)
  350.     switch (*s) {
  351.     case '~':
  352.         *vl = globtilde(nv, s);
  353.         break;
  354.     case '=':
  355.         *vl = globequal(nv, s);
  356.         break;
  357.     default:
  358.         break;
  359.     }
  360.     vl = nv;
  361.     return (vl);
  362. }
  363.  
  364. static Char *
  365. handleone(str, vl, action)
  366.     Char   *str, **vl;
  367.     int     action;
  368. {
  369.  
  370.     Char   *cp, **vlp = vl;
  371.  
  372.     switch (action) {
  373.     case G_ERROR:
  374.     setname(short2str(str));
  375.     blkfree(vl);
  376.     stderror(ERR_NAME | ERR_AMBIG);
  377.     break;
  378.     case G_APPEND:
  379.     trim(vlp);
  380.     str = Strsave(*vlp++);
  381.     do {
  382.         cp = Strspl(str, STRspace);
  383.         xfree((ptr_t) str);
  384.         str = Strspl(cp, *vlp);
  385.         xfree((ptr_t) cp);
  386.     }
  387.     while (*++vlp);
  388.     blkfree(vl);
  389.     break;
  390.     case G_IGNORE:
  391.     str = Strsave(strip(*vlp));
  392.     blkfree(vl);
  393.     break;
  394.     }
  395.     return (str);
  396. }
  397.  
  398. static Char **
  399. libglob(vl)
  400.     Char  **vl;
  401. {
  402.     int     gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT;
  403.     glob_t  globv;
  404.     char   *ptr;
  405.     int     nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
  406.  
  407.     if (!vl || !vl[0])
  408.     return(vl);
  409.  
  410.     globv.gl_offs = 0;
  411.     globv.gl_pathv = 0;
  412.     globv.gl_pathc = 0;
  413.  
  414.     if (nonomatch)
  415.     gflgs |= GLOB_NOCHECK;
  416.  
  417.     do {
  418.     ptr = short2qstr(*vl);
  419.     switch (glob(ptr, gflgs, 0, &globv)) {
  420.     case GLOB_ABEND:
  421.         setname(ptr);
  422.         stderror(ERR_NAME | ERR_GLOB);
  423.         /* NOTREACHED */
  424.     case GLOB_NOSPACE:
  425.         stderror(ERR_NOMEM);
  426.         /* NOTREACHED */
  427.     default:
  428.         break;
  429.     }
  430.     if (globv.gl_flags & GLOB_MAGCHAR) {
  431.         match |= (globv.gl_matchc != 0);
  432.         magic = 1;
  433.     }
  434.     gflgs |= GLOB_APPEND;
  435.     }
  436.     while (*++vl);
  437.     vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? 
  438.     NULL : blk2short(globv.gl_pathv);
  439.     globfree(&globv);
  440.     return (vl);
  441. }
  442.  
  443. Char   *
  444. globone(str, action)
  445.     Char   *str;
  446.     int     action;
  447. {
  448.  
  449.     Char   *v[2], **vl, **vo;
  450.     int gflg;
  451.  
  452.     noglob = adrof(STRnoglob) != 0;
  453.     gflag = 0;
  454.     v[0] = str;
  455.     v[1] = 0;
  456.     tglob(v);
  457.     gflg = gflag;
  458.     if (gflg == G_NONE)
  459.     return (strip(Strsave(str)));
  460.  
  461.     if (gflg & G_CSH) {
  462.     /*
  463.      * Expand back-quote, tilde and brace
  464.      */
  465.     vo = globexpand(v);
  466.     if (noglob || (gflg & G_GLOB) == 0) {
  467.         if (vo[0] == NULL) {
  468.         xfree((ptr_t) vo);
  469.         return (Strsave(STRNULL));
  470.         }
  471.         if (vo[1] != NULL) 
  472.         return (handleone(str, vo, action));
  473.         else {
  474.         str = strip(vo[0]);
  475.         xfree((ptr_t) vo);
  476.         return (str);
  477.         }
  478.     }
  479.     }
  480.     else if (noglob || (gflg & G_GLOB) == 0)
  481.     return (strip(Strsave(str)));
  482.     else
  483.     vo = v;
  484.  
  485.     vl = libglob(vo);
  486.     if ((gflg & G_CSH) && vl != vo)
  487.     blkfree(vo);
  488.     if (vl == NULL) {
  489.     setname(short2str(str));
  490.     stderror(ERR_NAME | ERR_NOMATCH);
  491.     }
  492.     if (vl[0] == NULL) {
  493.     xfree((ptr_t) vl);
  494.     return (Strsave(STRNULL));
  495.     }
  496.     if (vl[1]) 
  497.     return (handleone(str, vl, action));
  498.     else {
  499.     str = strip(*vl);
  500.     xfree((ptr_t) vl);
  501.     return (str);
  502.     }
  503. }
  504.  
  505. Char  **
  506. globall(v)
  507.     Char  **v;
  508. {
  509.     Char  **vl, **vo;
  510.     int gflg = gflag;
  511.  
  512.     if (!v || !v[0]) {
  513.     gargv = saveblk(v);
  514.     gargc = blklen(gargv);
  515.     return (gargv);
  516.     }
  517.  
  518.     noglob = adrof(STRnoglob) != 0;
  519.  
  520.     if (gflg & G_CSH)
  521.     /*
  522.      * Expand back-quote, tilde and brace
  523.      */
  524.     vl = vo = globexpand(v);
  525.     else
  526.     vl = vo = saveblk(v);
  527.  
  528.     if (!noglob && (gflg & G_GLOB)) {
  529.     vl = libglob(vo);
  530.     if ((gflg & G_CSH) && vl != vo)
  531.         blkfree(vo);
  532.     }
  533.     else
  534.     trim(vl);
  535.  
  536.     gargc = vl ? blklen(vl) : 0;
  537.     return (gargv = vl);
  538. }
  539.  
  540. void
  541. ginit()
  542. {
  543.     gargsiz = GLOBSPACE;
  544.     gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz);
  545.     gargv[0] = 0;
  546.     gargc = 0;
  547. }
  548.  
  549. void
  550. rscan(t, f)
  551.     register Char **t;
  552.     void    (*f) ();
  553. {
  554.     register Char *p;
  555.  
  556.     while (p = *t++)
  557.     while (*p)
  558.         (*f) (*p++);
  559. }
  560.  
  561. void
  562. trim(t)
  563.     register Char **t;
  564. {
  565.     register Char *p;
  566.  
  567.     while (p = *t++)
  568.     while (*p)
  569.         *p++ &= TRIM;
  570. }
  571.  
  572. void
  573. tglob(t)
  574.     register Char **t;
  575. {
  576.     register Char *p, c;
  577.  
  578.     while (p = *t++) {
  579.     if (*p == '~' || *p == '=')
  580.         gflag |= G_CSH;
  581.     else if (*p == '{' &&
  582.          (p[1] == '\0' || p[1] == '}' && p[2] == '\0'))
  583.         continue;
  584.     while (c = *p++)
  585.         if (isglob(c))
  586.         gflag |= (c == '{' || c == '`') ? G_CSH : G_GLOB;
  587.     }
  588. }
  589.  
  590. /*
  591.  * Command substitute cp.  If literal, then this is a substitution from a
  592.  * << redirection, and so we should not crunch blanks and tabs, separating
  593.  * words only at newlines.
  594.  */
  595. Char  **
  596. dobackp(cp, literal)
  597.     Char   *cp;
  598.     bool    literal;
  599. {
  600.     register Char *lp, *rp;
  601.     Char   *ep, word[MAXPATHLEN];
  602.  
  603.     if (pargv) {
  604. #ifdef notdef
  605.     abort();
  606. #endif
  607.     blkfree(pargv);
  608.     }
  609.     pargsiz = GLOBSPACE;
  610.     pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
  611.     pargv[0] = NOSTR;
  612.     pargcp = pargs = word;
  613.     pargc = 0;
  614.     pnleft = MAXPATHLEN - 4;
  615.     for (;;) {
  616.     for (lp = cp; *lp != '`'; lp++) {
  617.         if (*lp == 0) {
  618.         if (pargcp != pargs)
  619.             pword();
  620.         return (pargv);
  621.         }
  622.         psave(*lp);
  623.     }
  624.     lp++;
  625.     for (rp = lp; *rp && *rp != '`'; rp++)
  626. #ifdef ALTESC
  627.         if (*rp == escchar) {
  628. #else
  629.         if (*rp == '\\') {
  630. #endif
  631.         rp++;
  632.         if (!*rp)
  633.             goto oops;
  634.         }
  635.     if (!*rp)
  636.     oops:  stderror(ERR_UNMATCHED, '`');
  637.     ep = Strsave(lp);
  638.     ep[rp - lp] = 0;
  639.     backeval(ep, literal);
  640.     cp = rp + 1;
  641.     }
  642. }
  643.  
  644. static void
  645. backeval(cp, literal)
  646.     Char   *cp;
  647.     bool    literal;
  648. {
  649.     register int icnt, c;
  650.     register Char *ip;
  651.     struct command faket;
  652.     bool    hadnl;
  653.     int     pvec[2], quoted;
  654.     Char   *fakecom[2], ibuf[BUFSIZ];
  655.     char    tibuf[BUFSIZ];
  656.  
  657.     hadnl = 0;
  658.     icnt = 0;
  659.     quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
  660.     faket.t_dtyp = NODE_COMMAND;
  661.     faket.t_dflg = 0;
  662.     faket.t_dlef = 0;
  663.     faket.t_drit = 0;
  664.     faket.t_dspr = 0;
  665.     faket.t_dcom = fakecom;
  666.     fakecom[0] = STRfakecom1;
  667.     fakecom[1] = 0;
  668.  
  669.     /*
  670.      * We do the psave job to temporarily change the current job so that the
  671.      * following fork is considered a separate job.  This is so that when
  672.      * backquotes are used in a builtin function that calls glob the "current
  673.      * job" is not corrupted.  We only need one level of pushed jobs as long as
  674.      * we are sure to fork here.
  675.      */
  676.     psavejob();
  677.  
  678.     /*
  679.      * It would be nicer if we could integrate this redirection more with the
  680.      * routines in sh.sem.c by doing a fake execute on a builtin function that
  681.      * was piped out.
  682.      */
  683.     mypipe(pvec);
  684.     if (pfork(&faket, -1) == 0) {
  685.     struct wordent paraml;
  686.     struct command *t;
  687.  
  688.     (void) close(pvec[0]);
  689.     (void) dmove(pvec[1], 1);
  690.     (void) dmove(SHDIAG, 2);
  691.     initdesc();
  692.     /*
  693.      * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
  694.      * posted to comp.bugs.4bsd 12 Sep. 1989.
  695.      */
  696.     if (pargv)        /* mg, 21.dec.88 */
  697.         blkfree(pargv), pargv = 0, pargsiz = 0;
  698.     /* mg, 21.dec.88 */
  699.     arginp = cp;
  700.     while (*cp)
  701.         *cp++ &= TRIM;
  702.     (void) lex(¶ml);
  703.     if (seterr)
  704.         stderror(ERR_OLD);
  705.     alias(¶ml);
  706.     t = syntax(paraml.next, ¶ml, 0);
  707.     if (seterr)
  708.         stderror(ERR_OLD);
  709.     if (t)
  710.         t->t_dflg |= F_NOFORK;
  711. #ifdef SIGTSTP
  712.     (void) sigignore(SIGTSTP);
  713. #endif
  714. #ifdef SIGTTIN
  715.     (void) sigignore(SIGTTIN);
  716. #endif
  717. #ifdef SIGTTOU
  718.     (void) sigignore(SIGTTOU);
  719. #endif
  720.     execute(t, -1, NULL, NULL);
  721.     exitstat();
  722.     }
  723.     xfree((ptr_t) cp);
  724.     (void) close(pvec[1]);
  725.     c = 0;
  726.     ip = NULL;
  727.     do {
  728.     int     cnt = 0;
  729.  
  730.     for (;;) {
  731.         if (icnt == 0) {
  732.         int     i;
  733.  
  734.         ip = ibuf;
  735.         do
  736.             icnt = read(pvec[0], tibuf, BUFSIZ);
  737.         while (icnt == -1 && errno == EINTR);
  738. #ifdef __MINT__
  739. /* strip out carriage returns */
  740.         {
  741.         char *src, *dst;
  742.         int i;
  743.         src = dst = tibuf;
  744.  
  745.         for (i = icnt; i > 0; --i) {
  746.             if (*src == '\r')
  747.                 --icnt;
  748.             else
  749.                 *dst++ = *src;
  750.             src++;
  751.         }
  752.             }
  753. #endif
  754.         if (icnt <= 0) {
  755.             c = -1;
  756.             break;
  757.         }
  758.         for (i = 0; i < icnt; i++)
  759.             ip[i] = (unsigned char) tibuf[i];
  760.         }
  761.         if (hadnl)
  762.         break;
  763.         --icnt;
  764.         c = (*ip++ & TRIM);
  765.         if (c == 0)
  766.         break;
  767.         if (c == '\n') {
  768.         /*
  769.          * Continue around the loop one more time, so that we can eat
  770.          * the last newline without terminating this word.
  771.          */
  772.         hadnl = 1;
  773.         continue;
  774.         }
  775.         if (!quoted && (c == ' ' || c == '\t'))
  776.         break;
  777.         cnt++;
  778.         psave(c | quoted);
  779.     }
  780.     /*
  781.      * Unless at end-of-file, we will form a new word here if there were
  782.      * characters in the word, or in any case when we take text literally.
  783.      * If we didn't make empty words here when literal was set then we
  784.      * would lose blank lines.
  785.      */
  786.     if (c != -1 && (cnt || literal))
  787.         pword();
  788.     hadnl = 0;
  789.     } while (c >= 0);
  790.     (void) close(pvec[0]);
  791.     pwait();
  792.     prestjob();
  793. }
  794.  
  795. static void
  796. psave(c)
  797.     int    c;
  798. {
  799.     if (--pnleft <= 0)
  800.     stderror(ERR_WTOOLONG);
  801.     *pargcp++ = c;
  802. }
  803.  
  804. static void
  805. pword()
  806. {
  807.     psave(0);
  808.     if (pargc == pargsiz - 1) {
  809.     pargsiz += GLOBSPACE;
  810.     pargv = (Char **) xrealloc((ptr_t) pargv,
  811.                    (size_t) pargsiz * sizeof(Char *));
  812.     }
  813.     pargv[pargc++] = Strsave(pargs);
  814.     pargv[pargc] = NOSTR;
  815.     pargcp = pargs;
  816.     pnleft = MAXPATHLEN - 4;
  817. }
  818.  
  819. int
  820. Gmatch(string, pattern)
  821.     register Char *string, *pattern;
  822. {
  823.     register Char stringc, patternc;
  824.     int     match;
  825.     Char    rangec;
  826.  
  827.     for (;; ++string) {
  828.     stringc = *string & TRIM;
  829.     /*
  830.      * apollo compiler bug: switch (patternc = *pattern++) { dies
  831.      */
  832.     patternc = *pattern++;
  833.     switch (patternc) {
  834.     case 0:
  835.         return (stringc == 0);
  836.     case '?':
  837.         if (stringc == 0)
  838.         return (0);
  839.         break;
  840.     case '*':
  841.         if (!*pattern)
  842.         return (1);
  843.         while (*string)
  844.         if (Gmatch(string++, pattern))
  845.             return (1);
  846.         return (0);
  847.     case '[':
  848.         match = 0;
  849.         while (rangec = *pattern++) {
  850.         if (rangec == ']')
  851.             if (match)
  852.             break;
  853.             else
  854.             return (0);
  855.         if (match)
  856.             continue;
  857.         if (rangec == '-' && *(pattern-2) != '[' && *pattern  != ']') {
  858.             match = (stringc <= (*pattern & TRIM) &&
  859.                   (*(pattern-2) & TRIM) <= stringc);
  860.             pattern++;
  861.         }
  862.         else 
  863.             match = (stringc == (rangec & TRIM));
  864.         }
  865.         if (rangec == 0)
  866.         stderror(ERR_NAME | ERR_MISSING, ']');
  867.         break;
  868.     default:
  869.         if ((patternc & TRIM) != stringc)
  870.         return (0);
  871.         break;
  872.  
  873.     }
  874.     }
  875. }
  876.  
  877. void
  878. Gcat(s1, s2)
  879.     Char   *s1, *s2;
  880. {
  881.     register Char *p, *q;
  882.     int     n;
  883.  
  884.     for (p = s1; *p++;);
  885.     for (q = s2; *q++;);
  886.     n = (p - s1) + (q - s2) - 1;
  887.     if (++gargc >= gargsiz) {
  888.     gargsiz += GLOBSPACE;
  889.     gargv = (Char **) xrealloc((ptr_t) gargv,
  890.                    (size_t) gargsiz * sizeof(Char *));
  891.     }
  892.     gargv[gargc] = 0;
  893.     p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
  894.     for (q = s1; *p++ = *q++;);
  895.     for (p--, q = s2; *p++ = *q++;);
  896. }
  897.  
  898. #ifdef FILEC
  899. int
  900. sortscmp(a, b)
  901.     register Char **a, **b;
  902. {
  903. #if defined(NLS) && !defined(NOSTRCOLL)
  904.     char    buf[2048];
  905.  
  906. #endif
  907.  
  908.     if (!a)            /* check for NULL */
  909.     return (b ? 1 : 0);
  910.     if (!b)
  911.     return (-1);
  912.  
  913.     if (!*a)            /* check for NULL */
  914.     return (*b ? 1 : 0);
  915.     if (!*b)
  916.     return (-1);
  917.  
  918. #if defined(NLS) && !defined(NOSTRCOLL)
  919.     (void) strcpy(buf, short2str(*a));
  920.     return ((int) strcoll(buf, short2str(*b)));
  921. #else
  922.     return ((int) Strcmp(*a, *b));
  923. #endif
  924. }
  925.  
  926. #endif
  927.